/**
 * Created by lintao_alex on 2018/8/29
 */


namespace game {
    import BaseWindow = mengdao.BaseWindow;
    import IClass = mengdao.IClass;
    import ResourceEvent = RES.ResourceEvent;
    import UIPackage = fairygui.UIPackage;
    import BaseInjector = mengdao.BaseInjector;

    export class WindowManager extends BaseInjector{
        private readonly DYNAMIC_RES_PREFIX = 'dynamicResPrefix_';
        private _windowMap = new Map<IClass<BaseWindow>, WindowNode>();
        private _showStackProxy:BaseWindow[]=[];

        public openWindow(wClass:IClass<BaseWindow>){
            let wMap = this._windowMap;
            let wNode = wMap.get(wClass);
            if(!wNode) {
                wNode = new WindowNode(wClass)
                wNode.wObj = new wClass();
                wNode.wObj.context = this._context;
                wMap.set(wClass, wNode);
            }else if(this._showStackProxy.indexOf(wNode.wObj)>=0){
                return;
            }
            if(wNode.dataStatus==ReadyStatus.waiting) return;

            //todo 简化复杂度
            if(wNode.resStatus==ReadyStatus.ready){
                wNode.dataStatus = ReadyStatus.waiting;
                wNode.wObj.requestData({onSuccess:() => {
                    wNode.dataStatus = ReadyStatus.ready;
                    this.showWindow(wNode);
                }, onFail:() => {
                    wNode.dataStatus = ReadyStatus.notReady;
                }, callObj:this})
            }else if(wNode.resStatus==ReadyStatus.notReady){
                wNode.dataStatus = ReadyStatus.waiting;
                wNode.wObj.requestData({onSuccess:()=>{
                    wNode.dataStatus = ReadyStatus.ready;
                    if(wNode.resStatus==ReadyStatus.ready){
                        this.showWindow(wNode);
                    }
                },onFail:()=>{
                    wNode.dataStatus = ReadyStatus.notReady;
                }, callObj:this})
                this.prepareResource(wNode);
            }
        }

        public closeWindow(wClass:IClass<BaseWindow>){
            let wMap = this._windowMap;
            let wNode = wMap.get(wClass);
            let wObj = wNode.wObj;
            if(wNode && this._showStackProxy.indexOf(wObj)>=0){
                wObj.close(()=>{
                    ArrayUtils.remove(this._showStackProxy, wObj);
                    wObj.ui.removeFromParent();
                    this.dispatchEventWith(UIEvent.BE_CLOSED, wClass);
                },this)
            }
        }

        private showWindow(wNode:WindowNode){
            let wObj = wNode.wObj;
            wObj.__readyOpen();
            let layer = this.get(Layer).uiContainer;
            layer.addChild(wObj.ui)
            ArrayUtils.uniquePush(this._showStackProxy, wObj);
            wObj.open(()=>{
                this.dispatchEventWith(UIEvent.BE_OPENED, wNode.wClass)
            },this);
        }

        private prepareResource(wNode:WindowNode){
            wNode.resStatus = ReadyStatus.waiting;
            let wObj = wNode.wObj;
            let resGroupName = this.DYNAMIC_RES_PREFIX + egret.getQualifiedClassName(wObj);
            let pkgName = wObj.resPackage;
            let group = [pkgName]
            let atlas = pkgName+'@atlas0';
            if(RES.hasRes(atlas)) group.push(atlas);
            RES.createGroup(resGroupName, group, true);

            let checkRemoveResEvent = (evt:ResourceEvent)=>{
                if(evt.groupName!=resGroupName) return false;
                RES.removeEventListener(ResourceEvent.GROUP_COMPLETE, onGotRes, this);
                RES.removeEventListener(ResourceEvent.GROUP_LOAD_ERROR, onLoadErr, this);
                return true;
            }
            let onLoadErr = (evt:ResourceEvent)=>{
                if(checkRemoveResEvent(evt)){
                    wNode.resStatus = ReadyStatus.notReady;
                }
            }
            let onGotRes = (evt:ResourceEvent)=>{
                if(checkRemoveResEvent(evt)){
                    global[pkgName][pkgName+'Binder'].bindAll();
                    if(!UIPackage.getByName(pkgName)){
                        UIPackage.addPackage(pkgName);
                    }
                    wNode.resStatus = ReadyStatus.ready;
                    wObj.__createUI();
                    if(wNode.dataStatus==ReadyStatus.ready){
                        this.showWindow(wNode);
                    }
                }
            }
            RES.addEventListener(ResourceEvent.GROUP_COMPLETE, onGotRes, this);
            RES.addEventListener(ResourceEvent.GROUP_LOAD_ERROR, onLoadErr, this);
            RES.loadGroup(resGroupName);
        }
    }

    class WindowNode{
        public wObj:BaseWindow;
        public resStatus = ReadyStatus.notReady;
        public dataStatus = ReadyStatus.notReady;
        public constructor(public wClass:IClass<BaseWindow>){}
        public dispose(){

        }
    }
    enum ReadyStatus{
        notReady,
        waiting,
        ready
    }
}